#ifndef FILEBASE_HPP
#define FILEBASE_HPP

#include <fstream>
#include <sstream>
#include <vector>

#include "strbase.hpp"

class FileBase
{
public:

	static bool CheckExist(const std::string& path)
	{
#if 0
		return ((_access(path.c_str(), 0)) != -1);
#else
#if 0
		if (FILE *file = fopen(path.c_str(), "r")) {
			fclose(file);
			return true;
		}
		else {
			return false;
		}
#else
		std::ifstream ifs(path, std::ifstream::binary);
		if (!ifs.is_open())
			return false;
		ifs.close();
		return true;
#endif
#endif
	}

	static void WaitRemove(const std::string &path)
	{
		while (CheckExist(path))
		{
			//printf("try remove %s\n", path.c_str());
			remove(path.c_str());
		}
	}

	static bool LoadBinary(std::vector<char> &data, const char *path)
	{
		std::ifstream ifs(path, std::ifstream::binary);

		if (ifs.is_open())
		{
			// get pointer to associated buffer object
			std::filebuf* pbuf = ifs.rdbuf();

			// get file size using buffer's members
			std::size_t size = pbuf->pubseekoff(0, ifs.end, ifs.in);
			pbuf->pubseekpos(0, ifs.in);

			// allocate memory to contain file data
			data.assign(size, 0);

			// get file data
			pbuf->sgetn(data.data(), size);

			ifs.close();

			return true;
		}
		return false;
	}
#if 0
	static std::string GenTempPath(std::string folder = "./")
	{
#if 0
		time_t t;
		time(&t);
		std::ostringstream oss;
		oss << folder << t << "dl.jab";
		return oss.str();
#endif

		std::string tmp = folder + StrBase::RandomString();
		while (CheckExist(tmp))
		{
			tmp = folder + StrBase::RandomString();
		}
		return tmp;

	}
#endif
	static bool LoadBinaryStream(const char *path, std::stringstream &ss)
	{
		std::ifstream ifs(path, std::ifstream::binary);
		if (!ifs.is_open())
			return false;
		ss << ifs.rdbuf();
		ifs.close();
		return true;
	}

	static bool SaveBinaryStream(const char *path, std::stringstream &ss)
	{
		std::ofstream ofs(path, std::ofstream::binary);
		if (!ofs.is_open())
			return false;
		ofs << ss.str();
		ofs.close();
		return true;
	}

	static void OutputBinaryString(std::stringstream &ss, const std::string &str)
	{
		unsigned int nl = str.size();
		ss.write((char*)(&nl), sizeof(nl));
		ss.write((char*)(str.c_str()), nl);
	}

	static void InputBinaryString(std::stringstream &ss, std::string &str)
	{
		unsigned int nl;
		ss.read((char*)(&nl), sizeof(nl));
		char *buf = new char[nl];
		ss.read(buf, nl);
		str.assign(buf, buf + nl);
		delete[]buf;
	}

	static bool LoadStream(const char *path, std::stringstream &ss)
	{
		std::ifstream ifs(path);
		if (!ifs.is_open())
			return false;
		ss << ifs.rdbuf();
		ifs.close();
		return true;
	}

	static bool SaveStream(const char *path, std::stringstream &ss)
	{
		std::ofstream ofs(path);
		if (!ofs.is_open())
			return false;
		ofs << ss.str();
		ofs.close();
		return true;
	}

	static int Copy(std::string dst, std::string src)
	{
		std::ifstream ifs(src.c_str(), std::ifstream::binary);

		if (ifs.fail())
		{
			return 1;
		}
		std::ofstream ofs(dst.c_str(), std::ofstream::binary);
		if (ofs.fail())
		{
			ifs.close();
			return 2;
		}

		ofs << ifs.rdbuf();
		ifs.close();

		ofs.close();

		return 0;
	}
#if 0
	static int dlt(std::string fp)
	{
		return remove(fp.c_str());
	}

	static int ren(std::string newName, std::string oldName)
	{
		return rename(oldName.c_str(), newName.c_str());
	}
#endif

};

#if 0
class FileBaseW
{
public:



	static bool CheckExist(const std::wstring& path)
	{
		std::ifstream ifs(path, std::ifstream::binary);
		if (ifs.is_open())
		{
			ifs.close();
			return true;
		}
		else {
			return false;
		}
	}

	static void WaitRemove(const std::wstring &path)
	{
		while (CheckExist(path))
		{
			//printf("try remove %s\n", path.c_str());
			remove((char*)path.c_str());
		}
	}

	static bool LoadBinary(std::vector<char> &data, const wchar_t *path)
	{
		std::ifstream ifs(path, std::ifstream::binary);

		if (ifs.is_open())
		{
			// get pointer to associated buffer object
			std::filebuf* pbuf = ifs.rdbuf();

			// get file size using buffer's members
			std::size_t size = pbuf->pubseekoff(0, ifs.end, ifs.in);
			pbuf->pubseekpos(0, ifs.in);

			// allocate memory to contain file data
			data.assign(size, 0);

			// get file data
			pbuf->sgetn(data.data(), size);

			ifs.close();

			return true;
		}
		return false;
	}


	static bool LoadBinaryStream(const wchar_t *path, std::stringstream &ss)
	{
		std::ifstream ifs(path, std::ifstream::binary);
		if (!ifs.is_open())
			return false;
		ss << ifs.rdbuf();
		ifs.close();
		return true;
	}

	static bool SaveBinaryStream(const wchar_t *path, std::stringstream &ss)
	{
		std::ofstream ofs(path, std::ofstream::binary);
		if (!ofs.is_open())
			return false;
		ofs << ss.str();
		ofs.close();
		return true;
	}

	static bool LoadStream(const wchar_t *path, std::stringstream &ss)
	{
		std::ifstream ifs(path);
		if (!ifs.is_open())
			return false;
		ss << ifs.rdbuf();
		ifs.close();
		return true;
	}

	static bool SaveStream(const wchar_t *path, std::stringstream &ss)
	{
		std::ofstream ofs(path);
		if (!ofs.is_open())
			return false;
		ofs << ss.str();
		ofs.close();
		return true;
	}
};
#endif

#endif
